package cn.lcvc.xnc.authority.model;

import io.swagger.annotations.ApiModel;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.hibernate.validator.constraints.Length;
import org.hibernate.validator.constraints.Range;

import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * 权限和菜单的结合体
 * 说明：
 * 1.菜单类别
 * 主要分为菜单、按钮两种类型
 * 2.菜单打开方式
 * 主要分为组件、内部链接和外部链接三种方式。
 * （1）组件：常规模式，即菜单就是一个组件，需要在前端route中配置生成该菜单的路径，对应route的path属性。例如登录组件在vue的route中的path为/login
 * （2）内部链接：即该菜单只是一个跳转方式，负责跳转到其他组件,对应route中的如下配置。
 * {
 *     path: '/',
 *     redirect: 'login',
 *   },
 * （3）外部链接：即该菜单只是一个跳转方式，用于跳转到外部的链接，例如http://www.baidu.com
 */
@ApiModel(value="权限")
@Data
@NoArgsConstructor
public class SysPermission implements java.io.Serializable{
    private Long id;
    private Long parentId;//父权限
    @NotBlank(message = "权限名称不能为空")
    @Length(min = 2, max = 20, message = "权限名称的长度必须在 {min} - {max} 之间")
    private String name;//权限名
    @NotNull(message = "排序不能为空")
    private Integer sort;//排序，升序排列
    @NotNull(message = "菜单类型不能为空")
    @Range(min = 1,max = 2,message = "菜单类型的数值必须在{min} - {max}之间")
    private Integer type;//菜单类型（1表示菜单，2表示按钮）
    @Range(min = 1,max = 3,message = "菜单类型的数值必须在{min} - {max}之间")
    private Integer linkType;// 菜单打开方式：1.组件（常规模式），2.内部链接，3.外部链接
    private String redirect;//对应路由组件的redirect，表示跳转到另一个路由地址。根据vue路由组件的设定，如果本属性有值，则url将无效。
    private String url;//点击该组件后要跳转的地址，一般是内链或是外链。对应路由组件的：beforeEnter，例如routeNew.beforeEnter = () => { window.location.href = 'http://www.baidu.com'; };
    private String permission;//权限描述，主要根据该字段判断是否具有某权限


    //对应客户端vue的路由树形
    @Length(min = 1, max = 20, message = "组件名称的长度必须在 {min} - {max} 之间")
    private String component;//专门为vue等设计，表示组件的名称（对应vue路由的name）。如果是中文，也可以由本类的name树形决定，属于特定情况下的字段。
    @Length(min = 2, max = 200, message = "组件路由的长度必须在 {min} - {max} 之间")
    private String route;//表示路由的跳转地址（前端vue的跳转，通过点击该菜单跳转到的前端url），可以作为详细菜单的权限验证。当前未采用这个作为权限验证，因为如果采用则所有菜单动作都要添加进去，太麻烦，以后如果需要精确控制可以采用
    @Length(max = 200, message = "组件路径的长度不能超过{max}")
    //考虑到如果菜单有子菜单并不会打开，因此path路径这里不作为必填
    private String path;//vue组件在前端项目的地址，详细地址。如：/views/adminmanage/AdminManage.vue。
    @Length(max = 30, message = "图标名称的长度不能超过{max}")
    private String iconCls;//图标-css样式名称,要和前端的对应，非图片上传。如element的icon样式名：el-icon-platform-eleme
    @NotNull(message = "是否要求登录不能为空")
    private Boolean requireAuth;//要求登陆后才能访问，当前设计是给前端路由跳转时验证
    @NotNull(message = "是否可用不能为空")
    private Boolean enabled;//该菜单是否可用，也用于服务端验证。如果是查看账户拥有的菜单时，当前系统设计不会将不可用的菜单传递到前端。
    @NotNull(message = "是否可用不能为空")
    private Boolean display;//该菜单是否显示，提供给前端去进行处理。当前的element ui设计是如果菜单隐藏，则该菜单及其所有子菜单都不会在前台访问
    private Date createTime;

    //非数据库字段
    private List<SysPermission> children=new ArrayList<>();//该菜单拥有的子菜单/权限集合（递归）
    private Integer roleNumber;//使用角色数
}
